﻿/*
 * This file is part of CommunitySettlers.
 *
 * CommunitySettlers is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * CommunitySettlers is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with CommunitySettlers.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Author: Christoph Husse
 * 
 * Also checkout our homepage: http://communitysettlers.codeplex.com/
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Threading;
using System.Collections.ObjectModel;

namespace SettlersEngine.Exported
{
    public interface ISelectableVisual
    {
    }

    public class ResourceStackInfo
    {
        public Resource Type { get; internal set; }
        public Int32 Count { get; internal set; }
        public String Difference { get; internal set; }
        public ImageSource Thumbnail { get; internal set; }
    }

    public class BuildingListener : DependencyObject, ISelectableVisual
    {
        public static DependencyPropertyKey BuildingProgressPropertyKey = DependencyProperty.RegisterReadOnly("BuildingProgress", typeof(Double), typeof(BuildingListener), new PropertyMetadata(0.0));
        public static DependencyPropertyKey GradingProgressPropertyKey = DependencyProperty.RegisterReadOnly("GradingProgress", typeof(Double), typeof(BuildingListener), new PropertyMetadata(0.0));
        public static DependencyPropertyKey IsGradingPropertyKey = DependencyProperty.RegisterReadOnly("IsGrading", typeof(Boolean), typeof(BuildingListener), new PropertyMetadata(false));
        public static DependencyPropertyKey IsBuildingPropertyKey = DependencyProperty.RegisterReadOnly("IsBuilding", typeof(Boolean), typeof(BuildingListener), new PropertyMetadata(false));

        public static DependencyProperty BuildingProgressProperty = BuildingProgressPropertyKey.DependencyProperty;
        public static DependencyProperty GradingProgressProperty = GradingProgressPropertyKey.DependencyProperty;
        public static DependencyProperty IsGradingProperty = IsGradingPropertyKey.DependencyProperty;
        public static DependencyProperty IsBuildingProperty = IsBuildingPropertyKey.DependencyProperty;

        private int m_TypeIndex;
        private InternalBinding<ResourceStackInfo> m_Incoming = new InternalBinding<ResourceStackInfo>();
        private DispatcherTimer m_UpdateTimer = new DispatcherTimer();
        internal IBuildableObject Buildable { get; private set; }

        public String Name { get { return Buildable.Config.AnimationClass; } }
        public ImageSource Thumbnail { get { return Game.GetThumbnailForBuilding(TypeIndex); } }
        public int TypeIndex { get { return m_TypeIndex; } }
        public Double BuildingProgress { 
            get { return (Double)GetValue(BuildingProgressProperty); }
            private set {
                SetValue(BuildingProgressProperty, value);
                SetValue(IsBuildingProperty, !IsGrading && (BuildingProgress < 1.0));
            }
        }
        public Double GradingProgress
        {
            get { return (Double)GetValue(BuildingProgressProperty); }
            private set
            {
                SetValue(GradingProgressProperty, value);
                SetValue(IsGradingProperty, GradingProgress < 1.0);
            }
        }
        public Boolean IsGrading { get { return (Boolean)GetValue(IsGradingProperty); } }
        public Boolean IsBuilding { get { return (Boolean)GetValue(IsBuildingProperty); } }
        public GameInstance Game { get { return Buildable.Map.Game; } }

        /// <summary>
        /// Is true if user has explicitly set this building to build priority. This will cause the building to
        /// be the first one, along with other priority builds, in the build queue and nothing more.
        /// </summary>
        public Boolean HasBuildPriority { get; set; }
        /// <summary>
        /// Is true if user has explicitly stopped the build. This will cause all transporting settlers to drop
        /// down their resources they are carrying to the building.
        /// </summary>
        public Boolean HasBuildStopped { get; set; }
        /// <summary>
        /// Is true if user has explicitly stopped production. The building will stop production as soon as possible.
        /// </summary>
        public Boolean HasProductionStopped { get; set; }

        /// <summary>
        /// Represents all resources that are available or may soon become available for production. During build this
        /// contains all resources like stone, etc. that are available.
        /// </summary>
        public BindingList<ResourceStackInfo> Resources { get { return m_Incoming; } }

        /// <summary>
        /// Destroys the building.
        /// </summary>
        public void Destroy()
        {
        }

        /// <summary>
        /// Adjusts the production range to the specified area.
        /// </summary>
        public void ChangeProductionRange(System.Drawing.Point inNewCenter, int inNewRange)
        {
        }

        internal BuildingListener(IBuildableObject inBuildable)
        {
            m_TypeIndex = inBuildable.TypeIndex;
            Buildable = inBuildable;

            m_UpdateTimer.Tick += new EventHandler(m_UpdateTimer_Tick);
            m_UpdateTimer.Interval = TimeSpan.FromMilliseconds(500);
            m_UpdateTimer.Start();

            m_UpdateTimer_Tick(null, null);
        }

        void m_UpdateTimer_Tick(object sender, EventArgs e)
        {
            m_Incoming.ClearInternal();

            foreach (var query in Buildable.Queries)
            {
                int diff = -(query.Requested + query.Count - query.MaxStackSize);

                m_Incoming.AddInternal(new ResourceStackInfo()
                {
                    Difference = (diff > 0) ? "+" + diff : "" + diff,
                    Count = query.Count,
                    Type = query.ResourceType,
                    Thumbnail = Game.GetThumbnailForResource(query.ResourceType),
                });
            }

            foreach (var prov in Buildable.Providers)
            {
                int diff = prov.Available - prov.Count;

                m_Incoming.AddInternal(new ResourceStackInfo()
                {
                    Difference = (diff > 0) ? "+" + diff : "" + diff,
                    Count = prov.Count,
                    Type = prov.ResourceType,
                    Thumbnail = Game.GetThumbnailForResource(prov.ResourceType),
                });
            }
        }
    }
}
